﻿@using MudBlazor.Docs.Models
@using System.Text.RegularExpressions
@using System.Reflection
@using System.Web
@using Microsoft.Extensions.DependencyInjection
@using System.Globalization
@namespace MudBlazor.Docs.Components



<DocsPage MaxWidth="MaxWidth.Large">
    <DocsPageHeader ComponentLink="@ApiLink.GetComponentLinkFor(Type)"
                    Title="@Type.ConvertToCSharpSource()" SubTitle="API documentation">
    </DocsPageHeader>
    <DocsPageContent>
        <DocsPageSection>
            <SectionHeader>
                <Title>Properties</Title>
            </SectionHeader>
            <SectionContent Class="docs-content-api" FullWidth="true">
                <MudTable Items="@Properties" Elevation="0" Class="mx-0" Breakpoint="@Breakpoint.Sm">
                    <HeaderContent>
                        <MudTh>Name</MudTh>
                        <MudTh>Type</MudTh>
                        <MudTd>Default</MudTd>
                        <MudTh>Description</MudTh>
                    </HeaderContent>
                    <RowTemplate>
                        <MudTd Class="docs-content-api-cell" DataLabel="Name"><CodeInline>@context.Name</CodeInline></MudTd>
                        <MudTd Class="docs-content-api-cell" DataLabel="Type">@context.Type</MudTd>
                        <MudTd Class="docs-content-api-cell" DataLabel="Default">@PresentDefaultValue(context.Default)</MudTd>
                        <MudTd Class="docs-content-api-cell docs-content-api-description" DataLabel="Description">@(HttpUtility.HtmlDecode(context.Description))</MudTd>
                    </RowTemplate>
                </MudTable>
            </SectionContent>
        </DocsPageSection>
    </DocsPageContent>
</DocsPage>

<div style="display: none;">
    @RenderTheType()
</div>

@code {

    [Parameter] public Type Type { get; set; }

    private IEnumerable<ApiProperty> Properties
    {
        get
        {
            foreach (var info in Type.GetPropertyInfosWithAttribute<ParameterAttribute>())
            {
                if (info.GetCustomAttributes(typeof(System.ObsoleteAttribute), true).Length == 0)
                {
                    yield return new ApiProperty()
                    {
                        Name=info.Name,
                        Type = info.PropertyType.ConvertToCSharpSource(),
                        Description = GetDescription(Type, info),
                        Default = GetDefaultValue(info),
                    };
                }
            }
        }
    }

    private string GetDescription(Type type, PropertyInfo info)
    {
        var doc = DocStrings.GetPropertyDescription(type, info.Name);
        doc = Regex.Replace(doc??"", @"</?.+?>", "");
        return doc;
    }

    // used for default value getting
    object _comp_instance;

    RenderFragment RenderTheType()
    {
        return new RenderFragment(builder =>
        {
            builder.OpenComponent(0, Type);
            builder.AddComponentReferenceCapture(1, inst => { _comp_instance = inst; });
            builder.CloseComponent();
        });
    }

    private object GetDefaultValue(PropertyInfo info)
    {
        try
        {
            if (_comp_instance == null)
            {
                return null;
                //RenderTheType();
            }
            return info.GetValue(_comp_instance);
        }
        catch(Exception){}
        return null;
    }

    // TODO: document public methods later
    //IEnumerable<ApiMethod> Methods {
    //    get {
    //        foreach (var info in Type.GetMethods(BindingFlags.Instance|BindingFlags.Public))
    //        {
    //            var doc=info.GetDocumentation();
    //            doc = Regex.Replace(doc??"", @"</?.+?>", "");
    //            yield return new ApiItem()
    //            {
    //                Name=info.Name, 
    //                ReturnType = info.PropertyType.ConvertToCSharpSource(), 
    //                Description = doc
    //            };
    //        }
    //    }
    //}
    DefaultConverter<object> _converter = new DefaultConverter<object>() { Culture= CultureInfo.InvariantCulture };

    private string PresentDefaultValue(object @default)
    {
        if (@default == null)
            return "null";
        if (@default.GetType()==typeof(string))
            return $"\"{@default}\"";
        if (@default.GetType().IsEnum)
            return $"{@default.GetType().Name}.{@default}";
        if (Nullable.GetUnderlyingType(@default.GetType())!=null)
            return _converter.Set(@default);
        if (@default.GetType().IsGenericType) // for instance event callbacks
            return "";
        if (@default.GetType().IsValueType)
            return _converter.Set( @default);
        return "";
    }

}
